package com.delivery.deliverysystem.service.impl;


import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.delivery.deliverysystem.common.ServerResponse;
import com.delivery.deliverysystem.service.BackendSystemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

@Service
@Slf4j
public class BackendSystemServiceImpl implements BackendSystemService {

    @Value("${spring.datasource.url}")
    private String datasourceUrl;
    @Value("${spring.datasource.username}")
    private String datasourceUsername;
    @Value("${spring.datasource.password}")
    private String datasourcePassword;
    @Value("${aliyun.oss.endpoint}")
    private String ossEndpoint;
    @Value("${aliyun.oss.accessKeyId}")
    private String ossAccessKeyId;
    @Value("${aliyun.oss.accessKeySecret}")
    private String ossAccessKeySecret;
    @Value("${aliyun.oss.bucketName}")
    private String ossBucketName;
    @Value("${file.backup-path}")
    private String backupPath;
    @Value("${file.mysqldump-path}")
    private String mysqldumpPath;
    @Value("${file.mysql-path}")
    private String mysqlPath;

    /**
     * 备份送货单相关数据
     * @param companyName
     * @return
     */
    @Override
    public ServerResponse backup(String companyName) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = dateFormat.format(new Date());
        String fileName = companyName + "_" + dateStr + ".sql";
        // 从配置文件中解析数据库连接信息
        String databaseName = datasourceUrl.split("/")[3].split("\\?")[0]; // 提取数据库名称
        String host = datasourceUrl.split("//")[1].split(":")[0]; // 提取主机地址
        String port = datasourceUrl.split(":")[3].split("/")[0]; // 提取端口号
//        String mysqldumpPath = "C://Program Files/MySQL/MySQL Server 8.0/bin/mysqldump"; // Windows系统路径
//        String mysqldumpPath = "/usr/bin/mysqldump"; // Linux系统路径
        // 构造 mysqldump 命令
        String command = String.format("%s -h %s -P %s -u %s -p%s %s delivery delivery_detail",
                mysqldumpPath, host, port, datasourceUsername, datasourcePassword, databaseName);
        try {
            // 执行命令并将输出重定向到内存中的ByteArrayOutputStream
            Process process = Runtime.getRuntime().exec(command);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            InputStream inputStream = process.getInputStream();
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            inputStream.close();
            outputStream.close();

            int exitCode = process.waitFor();
            if (exitCode == 0) {
                // 保存到本地文件夹
                saveToLocal(outputStream.toByteArray(), fileName);
                //上传到OSS
                uploadToOss(outputStream.toByteArray(), fileName,companyName);
                // 备份成功
                return ServerResponse.createBySuccess("备份成功，已上传到OSS并保存到本地");
            } else {
                return ServerResponse.createBySuccess("备份失败，错误码：" + exitCode);
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            return ServerResponse.createByError("备份失败，异常：" + e.getMessage());
        }
    }

    /**
     * 备份到云端oss上
     * @param fileContent
     * @param fileName
     * @param companyName
     * @return
     */
    private ServerResponse uploadToOss(byte[] fileContent, String fileName,String companyName) {
        // 初始化OSS客户端
        OSS ossClient = new OSSClientBuilder().build(ossEndpoint, ossAccessKeyId, ossAccessKeySecret);

        try {
            // 上传文件到OSS
            String ossFilePath = companyName + "/" + fileName; // OSS中的存储路径
            ossClient.putObject(ossBucketName, ossFilePath, new ByteArrayInputStream(fileContent));
            return ServerResponse.createBySuccess("备份文件已上传到OSS，路径：" + ossFilePath);
        } catch (Exception e) {
            e.printStackTrace();
            return ServerResponse.createByError("上传到OSS失败，异常：" + e.getMessage());
        } finally {
            // 关闭OSS客户端
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 备份到本地文件夹中
     * @param fileContent
     * @param fileName
     */
    private void saveToLocal(byte[] fileContent, String fileName) {
        File backupDir = new File(backupPath);
        if (!backupDir.exists()) {
            backupDir.mkdirs(); // 如果目录不存在，创建目录
        }
        File backupFile = new File(backupDir, fileName);
        try (FileOutputStream fos = new FileOutputStream(backupFile)) {
            fos.write(fileContent);
            log.info("备份文件已保存到本地路径：{}", backupFile.getAbsolutePath());
        } catch (IOException e) {
            log.error("保存备份文件到本地失败，异常：", e);
        }
    }
    /**
     * 恢复备份过的数据
     */
    @Override
    public ServerResponse restore(MultipartFile file) {
        if (file.isEmpty()) {
            return ServerResponse.createByError("上传的文件为空");
        }

        // 从配置文件中解析数据库连接信息
        String databaseName = datasourceUrl.split("/")[3].split("\\?")[0]; // 提取数据库名称
        String host = datasourceUrl.split("//")[1].split(":")[0]; // 提取主机地址
        String port = datasourceUrl.split(":")[3].split("/")[0]; // 提取端口号

        // 构造 mysql 命令
        String command = String.format("%s -h %s -P %s -u %s -p%s %s",
                mysqlPath,host, port, datasourceUsername, datasourcePassword, databaseName);

        try {
            // 创建临时文件
            File tempFile = File.createTempFile("restore", ".sql");
            file.transferTo(tempFile);

            // 执行命令
            ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
            processBuilder.redirectInput(tempFile);
            Process process = processBuilder.start();

            int exitCode = process.waitFor();
            if (exitCode == 0) {
                return ServerResponse.createBySuccess("数据库恢复成功");
            } else {
                return ServerResponse.createByError("数据库恢复失败，错误码：" + exitCode);
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            return ServerResponse.createByError("恢复数据库失败，异常：" + e.getMessage());
        } finally {
            // 删除临时文件
            File tempFile = new File(file.getOriginalFilename());
            if (tempFile.exists()) {
                tempFile.delete();
            }
        }
    }
}
